스택(Stack)과 큐(Queue)

스택과 큐는 둘 다 선형 자료구조로, 아이템을 저장하고 처리하는 데 쓰이지만, 작동 방식과 용도가 다릅니다. 소프트웨어 엔지니어 면접에서 기본적으로 잘 알고 있어야 하는 내용입니다.

1. 스택 (Stack)

개요

주요 연산

시각적 예시

스택 (맨 위가 오른쪽):

[Bottom] 1 <-- 2 <-- 3 <-- 4 [Top]

pop하면 4가 나옵니다. push(5)하면 맨 위가 5가 됩니다.

주요 용도

2. 큐 (Queue)

개요

주요 연산

시각적 예시

큐 (앞이 왼쪽, 뒤가 오른쪽):

[Front] 1 --> 2 --> 3 --> 4 [Back]

dequeue하면 1이 나옵니다. enqueue(5)하면 뒤가 5가 됩니다.

주요 용도

비교 표

특징 스택(Stack) 큐(Queue)
순서 LIFO (후입선출) FIFO (선입선출)
주요 메서드 push, pop, peek, isEmpty enqueue, dequeue, peek, isEmpty
주 사용처 실행 취소, 콜 스택, DFS 스케줄링, BFS, 버퍼링
실생활 비유 접시 쌓기 티켓 줄

스택(Stack)과 큐(Queue): 구현, 사용 사례, 시간 복잡도

스택과 큐를 어떻게 구현하는지, 주요 용도와 계산 효율성을 알아보겠습니다.

1. 스택(Stack)

A. 구현 방법

1. 배열을 이용한 구현 (Java 예제)

class Stack {
    private int[] arr;
    private int top;

    public Stack(int size) {
        arr = new int[size];
        top = -1;
    }
    public void push(int x) { arr[++top] = x; }
    public int pop() { return arr[top--]; }
    public int peek() { return arr[top]; }
    public boolean isEmpty() { return top == -1; }
}

2. 연결 리스트를 이용한 구현

class Node {
    int data;
    Node next;
    Node(int d) { data = d; }
}

class Stack {
    private Node top;
    public void push(int x) { Node n = new Node(x); n.next = top; top = n; }
    public int pop() { int val = top.data; top = top.next; return val; }
    public int peek() { return top.data; }
    public boolean isEmpty() { return top == null; }
}

3. 내장 라이브러리 사용

B. 사용 사례

C. 시간 복잡도

연산 배열/연결 리스트 구현 시 시간 복잡도
push O(1)
pop O(1)
peek O(1)
isEmpty O(1)

2. 큐(Queue)

A. 구현 방법

1. 배열을 이용한 구현 (원형 큐 예제)

class Queue {
    private int[] arr;
    private int front, rear, size, capacity;

    public Queue(int cap) {
        arr = new int[cap];
        capacity = cap;
        front = size = 0;
        rear = cap - 1;
    }
    public void enqueue(int x) {
        if (size == capacity) throw new RuntimeException("Overflow");
        rear = (rear + 1) % capacity;
        arr[rear] = x; size++;
    }
    public int dequeue() {
        if (size == 0) throw new RuntimeException("Underflow");
        int item = arr[front];
        front = (front + 1) % capacity;
        size--; return item;
    }
    public int peek() { return arr[front]; }
    public boolean isEmpty() { return size == 0; }
}

2. 연결 리스트를 이용한 구현

class Node {
    int data;
    Node next;
    Node(int d) { data = d; }
}

class Queue {
    Node front, rear;
    public void enqueue(int x) {
        Node n = new Node(x);
        if (rear == null) front = rear = n;
        else { rear.next = n; rear = n; }
    }
    public int dequeue() {
        if (front == null) throw new RuntimeException("Underflow");
        int val = front.data;
        front = front.next;
        if (front == null) rear = null;
        return val;
    }
    public int peek() { return front.data; }
    public boolean isEmpty() { return front == null; }
}

3. 내장 라이브러리 사용

B. 사용 사례

C. 시간 복잡도

연산 배열/연결 리스트 구현 시 시간 복잡도
enqueue O(1)
dequeue O(1)
peek/front O(1)
isEmpty O(1)

3. 요약 표

항목 스택(Stack) 큐(Queue)
접근 방식 LIFO (후입선출) FIFO (선입선출)
주요 연산 push, pop, peek enqueue, dequeue, peek
주요 사용 사례 재귀, 실행취소, DFS 스케줄링, BFS, 버퍼링
일반적 구현 배열, 연결 리스트, 라이브러리 배열, 연결 리스트, 라이브러리
시간 복잡도 모든 기본 연산 O(1) 모든 기본 연산 O(1)